package com.briup.pai.service.impl;

import cn.hutool.core.io.FileUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.briup.pai.common.constant.CommonConstant;
import com.briup.pai.common.constant.DatasetConstant;
import com.briup.pai.common.enums.ResultCodeEnum;
import com.briup.pai.common.exception.BriupAssert;
import com.briup.pai.convert.EntityConvert;
import com.briup.pai.dao.EntityMapper;
import com.briup.pai.entity.po.Classify;
import com.briup.pai.entity.po.Dataset;
import com.briup.pai.entity.po.Entity;
import com.briup.pai.entity.vo.EntityInClassifyVO;
import com.briup.pai.entity.vo.EntityPageVO;
import com.briup.pai.entity.vo.PageVO;
import com.briup.pai.service.IClassifyService;
import com.briup.pai.service.IDatasetService;
import com.briup.pai.service.IEntityService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
@CacheConfig(cacheNames = DatasetConstant.DATASET_CACHE_PREFIX)
public class EntityServiceImpl extends ServiceImpl<EntityMapper, Entity> implements IEntityService {

    @Autowired
    private EntityConvert entityConvert;
    @Autowired
    @Lazy
    private IClassifyService classifyService;
    @Autowired
    @Lazy
    private IDatasetService datasetService;
    @Value("${upload.nginx-server}")
    private String nginxServer;
    @Value("${upload.nginx-file-path}")
    private String nginxFilePath;

    @Override
    public List<EntityInClassifyVO> getEntityByClassifyId(Integer classifyId) {
        // 查询
        LambdaQueryWrapper<Entity> lqw = new LambdaQueryWrapper<>();
        lqw.eq(Entity::getClassifyId, classifyId);
        return entityConvert.po2EntityInClassifyVOList(this.baseMapper.selectList(lqw));

    }

    @Override
    public PageVO<EntityPageVO> getEntityByPage(Integer classifyId, Long pageNum) {
        // 确认分类必须存在
        Classify classify = BriupAssert.requireNotNull(
                classifyService,
                Classify::getId,
                classifyId,
                ResultCodeEnum.DATA_NOT_EXIST);
        // 分页
        IPage<Entity> page = new Page<>(pageNum, DatasetConstant.ENTITY_PAGE_SIZE);
        // 查询
        LambdaQueryWrapper<Entity> lqw = new LambdaQueryWrapper<>();
        lqw.eq(Entity::getClassifyId, classifyId);
        // 构建返回的对象
        PageVO<EntityPageVO> pageVO = new PageVO<>();
        pageVO.setTotal(page.getTotal());
        pageVO.setData(entityConvert.po2EntityPageVOList(
                this.list(page, lqw).stream().peek(
                        entity -> {
                            // 重新将entity的url编辑一下，加入前缀，因为数据库里只保存了图片的名字(entityUrl)
                            // http://localhost:89/datasetId/classifyName/entityUrl
                            // 调用准备好的工具方法create拼接
                            entity.setEntityUrl(CommonConstant.createEntityPath(
                                    nginxServer,
                                    classify.getDatasetId(),
                                    classify.getClassifyName(),
                                    entity.getEntityUrl()));
                        }
                ).toList()));
        return pageVO;
    }

    @Override
    @Transactional
    @CacheEvict(
            key = "T(com.briup.pai.common.constant.CommonConstant).DETAIL_CACHE_PREFIX+':'+#datasetId"
    )
    public void removeEntityByBatch(Integer datasetId, Integer classifyId, List<Integer> entityIds) {
        // 参数校验
        Dataset dataset = BriupAssert.requireNotNull(
                datasetService,
                Dataset::getId,
                datasetId, ResultCodeEnum.DATA_NOT_EXIST);
        Classify classify = BriupAssert.requireNotNull(
                classifyService,
                Classify::getId,
                classifyId, ResultCodeEnum.DATA_NOT_EXIST);
        BriupAssert.requireEqual(
                dataset.getId(),
                classify.getDatasetId(),
                ResultCodeEnum.PARAM_IS_ERROR);

        // TODO 数据集不能已经用于模型的训练、优化、评估（此功能后续学完模型模块再添加）

        // 查出文件夹下的图片文件
        entityIds.stream().map(
                entityId ->
                        CommonConstant.createEntityPath(
                                nginxFilePath,
                                datasetId,
                                classify.getClassifyName(),
                                this.getById(entityId).getEntityUrl())
        ).forEach(FileUtil::del);

        // 数据库删除
        this.removeBatchByIds(entityIds);
    }
}